package com.ifp.opengate.boot.config;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.validation.Validator;

import com.ifp.adapter.common.AdapterCanstants;
import com.ifp.core.context.ClogicContext;
import com.ifp.core.log.Trace;
import com.ifp.opengate.boot.bean.OpenGateRoute;
import com.ifp.opengate.boot.constants.Constants;
import com.ifp.opengate.boot.factory.IfpRedisRateLimiter;
import com.ifp.opengate.boot.task.ConnectorCacheDataTask;

import reactor.core.publisher.Mono;

/**
 * 项目名：ifp-gateway <br>
 * 包名：com.ifp.opengate.boot.config <br>
 * 类名：RateLimiterConfig <br>
 * 描述：
 *
 * @author Suremotoo
 * @create 2021-06-09 14:28
 */
@Configuration
public class RateLimiterConfig {

    /**
     * 使用自定义的限流类
     * 
     * @param redisTemplate
     * @param redisScript
     * @param validator
     * @return
     */
    @Bean
    @Primary
    public IfpRedisRateLimiter customRedisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate,
        @Qualifier(IfpRedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript<List<Long>> redisScript, Validator validator) {
        return new IfpRedisRateLimiter(redisTemplate, redisScript, validator);
    }

    @Autowired
    private ConnectorCacheDataTask connectorCacheDataTask;

    @Primary
    @Bean(value = "remoteAddrKeyResolver")
    public KeyResolver remoteAddrKeyResolver() {
        return exchange -> {
            String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            Trace.logInfo(Trace.MODULE_ACTION, "remoteAddrKeyResolver 限流规则 ip {}：", hostAddress);
            return Mono.just(hostAddress);
        };
    }

    @Bean(value = "userKeyResolver")
    public KeyResolver userKeyResolver() {
        return exchange -> {
            ClogicContext clogicContext = (ClogicContext)exchange.getAttributes().get(Constants.CL_CONTEXT);
            Map<String, Object> dataMap = clogicContext.getDataMap();
            Map<String, Object> headerMap = (Map<String, Object>)dataMap.get(AdapterCanstants.HEADER);
            String userId = String.valueOf(headerMap.get("userId"));
            Trace.logInfo(Trace.MODULE_ACTION, "userKeyResolver 限流规则 userId {}：", userId);
            return Mono.just(userId);
        };
    }

    /**
     * 按照Path限流
     *
     * @return key
     */
    @Bean(value = "pathKeyResolver")
    public KeyResolver pathKeyResolver() {
        return exchange -> {
            Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
            OpenGateRoute openGateRoute = connectorCacheDataTask.getRouteOfMap().get(route.getId());
            // System.out.println("pathKeyResolver 限流接口:" + openGateRoute.getRouteId() + openGateRoute.getRoutePath());
            Trace.logInfo(Trace.MODULE_ACTION, "pathKeyResolver 限流规则 path {}-{}：", openGateRoute.getRouteId(),
                openGateRoute.getRoutePath());
            return Mono.just(exchange.getRequest().getPath().toString());
        };
    }

}
